Download Seurat object.
#scp schea2@hpc3.rcic.uci.edu:/share/crsp/lab/alcalof/schea2/20220414-seurat/all-aggr-seurat.Robj /Volumes/all_ssd/20220414-seurat
Load libraries.
library(Seurat)
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Registered S3 method overwritten by 'htmlwidgets':
method from
print.htmlwidget tools:rstudio
Attaching SeuratObject
There were 20 warnings (use warnings() to see them)
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
method from
print.tbl_lazy
print.tbl_sql
[30m── [1mAttaching packages[22m ──────────────────────────────── tidyverse 1.3.1 ──[39m
[30m[32m✔[30m [34mggplot2[30m 3.3.6 [32m✔[30m [34mpurrr [30m 0.3.4
[32m✔[30m [34mtibble [30m 3.1.7 [32m✔[30m [34mdplyr [30m 1.0.9
[32m✔[30m [34mtidyr [30m 1.2.0 [32m✔[30m [34mstringr[30m 1.4.0
[32m✔[30m [34mreadr [30m 2.1.1 [32m✔[30m [34mforcats[30m 0.5.1[39m
[30m── [1mConflicts[22m ─────────────────────────────────── tidyverse_conflicts() ──
[31m✖[30m [34mdplyr[30m::[32mfilter()[30m masks [34mstats[30m::filter()
[31m✖[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()[39m
library(pracma)
Attaching package: ‘pracma’
The following object is masked from ‘package:purrr’:
cross
library(scales)
Attaching package: ‘scales’
The following object is masked from ‘package:purrr’:
discard
The following object is masked from ‘package:readr’:
col_factor
Load Seurat object.
load("/Volumes/all_ssd/20220414-seurat/all-aggr-seurat.Robj")
Plot histogram of number of umi’s.
ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA)) +
geom_histogram() +
geom_vline(xintercept = mean(all.aggr$nCount_RNA), color = "blue") +
geom_vline(xintercept = median(all.aggr$nCount_RNA), color = "red") +
scale_x_continuous(trans = "log10")

Plot histogram of number of genes.
ggplot(data = all.aggr@meta.data, mapping = aes(x = nFeature_RNA)) +
geom_histogram() +
geom_vline(xintercept = mean(all.aggr$nFeature_RNA), color = "blue") +
geom_vline(xintercept = median(all.aggr$nFeature_RNA), color = "red") +
scale_x_continuous(trans = "log10")

Calculate % mitochondrial genes.
all.aggr[["percent.mt"]] <- PercentageFeatureSet(all.aggr, pattern = "^mt-")
head(all.aggr@meta.data)
Plot histogram of % mitochondrial genes.
ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt)) +
geom_histogram() +
geom_vline(xintercept = mean(all.aggr$percent.mt), color = "blue") +
geom_vline(xintercept = median(all.aggr$percent.mt), color = "red") +
scale_x_continuous(trans = "log10")

Largest portion of distribution normal. Obvious hump of cells with low % mitochondrial genes. Odd that they have low % mitochondrial genes. Usually low is better, but here, most cells have a % between 1 and 10.
% mitochondrial genes is dependent on number of genes detected. Do these correpond to cells with low numbers of genes?
ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA)) +
geom_point(size = 0.1) +
geom_vline(xintercept = mean(all.aggr$percent.mt), color = "blue") +
geom_vline(xintercept = median(all.aggr$percent.mt), color = "red") +
scale_x_continuous(trans = "log10") +
scale_y_continuous(trans = "log10")

Calculate outliers using median absolute deviation.
all.aggr$log.mito <- log10(all.aggr$percent.mt)
median.mito <- median(all.aggr$log.mito)
all.aggr$d.mito <- abs(all.aggr$log.mito - median.mito)
md.mito <- mad(all.aggr$log.mito)
all.aggr$mito.out <- all.aggr$d.mito > md.mito*3
sum(all.aggr$mito.out)
[1] 6681
ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA, color = mito.out)) +
geom_point(size = 0.1) +
scale_x_continuous(trans = "log10") +
scale_y_continuous(trans = "log10")

What does histogram of % mito now look?
mito.hist <- ggplot() +
geom_histogram(data = all.aggr@meta.data, mapping = aes(x = percent.mt, fill = mito.out, color = mito.out), alpha = 0.5, size = 0.33) +
scale_x_continuous(trans = "log10", labels = scales::percent_format(scale = 1)) +
scale_fill_discrete(labels = c("<=3 MAD", "> 3 MAD")) +
scale_color_discrete(labels = c("<=3 MAD", "> 3 MAD")) +
labs(x = "% Mitochondrial Genes", y = "Number of Cells", fill = "", color = "", tag = "A") +
theme_classic(base_size = 7) +
theme(plot.title = element_text(hjust = 0.5), legend.key.size = unit(7, "pt"), legend.position = "top", plot.tag = element_text(size = 9, face = "bold"))
mito.hist
ggsave(plot = mito.hist, filename = "mito-hist-plot-low-quality-cells.png", device = "png", units = "in", width = 2.16, height = 3)

Genes?
ggplot(data = all.aggr@meta.data, mapping = aes(x = nFeature_RNA, color = mito.out)) +
geom_histogram() +
scale_x_continuous(trans = "log10")

UMIs?
ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, color = mito.out)) +
geom_histogram() +
scale_x_continuous(trans = "log10")

What does vln plot mito now look?
mito.plot <- ggplot() +
geom_jitter(data = all.aggr@meta.data, mapping = aes(y = percent.mt, x = mito.out, group = mito.out), stroke = 0, size = 0.25) +
geom_violin(data = all.aggr@meta.data, mapping = aes(y = percent.mt, x = mito.out, color = mito.out), alpha = 0) +
scale_x_discrete(labels = c("<= 3MAD", "> 3MAD")) +
scale_y_continuous(trans = "log10", labels = scales::percent_format(scale = 1)) +
labs(x = "", y = "% Mitochondrial Genes", fill = "", color = "", tag = "A") +
theme_classic(base_size = 7) +
theme(plot.title = element_text(hjust = 0.5), legend.position = "none", plot.tag = element_text(size = 9, face = "bold"))
mito.plot
ggsave(plot = mito.plot, filename = "mito-vln-plot-low-quality-cells.png", device = "png", units = "in", width = 2.16, height = 4.5)

Can we find outliers among genes after already filtering out outliers from mito?
all.aggr$log.gene <- log10(all.aggr$nFeature_RNA)
median.gene <- median(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% pull(log.gene))
all.aggr$d.gene <- abs(all.aggr$log.gene - median.gene)
md.gene <- mad(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% pull(log.gene))
all.aggr$gene.out <- all.aggr$d.gene > md.gene*3
sum(all.aggr$gene.out)
[1] 65
Where do these cells lie along histogram of number of genes?
gene.hist <- ggplot() +
geom_histogram(data = all.aggr@meta.data, mapping = aes(x = nFeature_RNA, fill = gene.out, color = gene.out), alpha = 0.5, size = 0.33) +
scale_x_continuous(trans = "log10", breaks=trans_breaks('log10', function(x) 10^x), labels=trans_format('log10', math_format(10^.x))) +
scale_fill_discrete(labels = c("<=3 MAD", "> 3 MAD")) +
scale_color_discrete(labels = c("<=3 MAD", "> 3 MAD")) +
labs(x = "Number of Genes", y = "Number of Cells", fill = "", color = "", tag = "B") +
theme_classic(base_size = 7) +
theme(plot.title = element_text(hjust = 0.5), legend.key.size = unit(7, "pt"), legend.position = "top", plot.tag = element_text(size = 9, face = "bold"))
gene.hist
ggsave(plot = gene.hist, filename = "gene-hist-plot-low-quality-cells.png", device = "png", units = "in", width = 2.16, height = 3)

Along number of umis?
ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE), mapping = aes(x = nCount_RNA, color = gene.out)) +
geom_histogram() +
scale_x_continuous(trans = "log10")

What does vln plot genes now look?
gene.plot <- ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE)) +
geom_jitter(mapping = aes(y = nFeature_RNA, x = gene.out, group = gene.out), stroke = 0, size = 0.25) +
geom_violin(mapping = aes(y = nFeature_RNA, x = gene.out, color = gene.out), alpha = 0) +
scale_x_discrete(labels = c("<= 3MAD", "> 3MAD")) +
scale_y_continuous(trans = "log10", breaks=trans_breaks('log10', function(x) 10^x), labels=trans_format('log10', math_format(10^.x))) +
labs(x = "", y = "Number of Genes", fill = "", color = "", tag = "B") +
theme_classic(base_size = 7) +
theme(plot.title = element_text(hjust = 0.5), legend.position = "none", , plot.tag = element_text(size = 9, face = "bold"))
gene.plot
ggsave(plot = gene.plot, filename = "gene-vln-plot-low-quality-cells.png", device = "png", units = "in", width = 2.16, height = 4.5)

Can we find outliers among umis after already filtering out mito and genes?
all.aggr$log.umi <- log10(all.aggr$nCount_RNA)
median.umi <- median(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE) %>% pull(log.umi))
all.aggr$d.umi <- abs(all.aggr$log.umi - median.umi)
md.umi <- mad(all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE) %>% pull(log.umi))
all.aggr$umi.out <- all.aggr$d.umi > md.umi*3
sum(all.aggr$umi.out)
[1] 768
Where do these lie along umis?
umi.hist <- ggplot() +
geom_histogram(data = all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE), mapping = aes(x = nCount_RNA, color = umi.out, fill = umi.out), alpha = 0.5, size = 0.33) +
scale_x_continuous(trans = "log10", breaks=trans_breaks('log10', function(x) 10^x), labels=trans_format('log10', math_format(10^.x))) +
scale_fill_discrete(labels = c("<=3 MAD", "> 3 MAD")) +
scale_color_discrete(labels = c("<=3 MAD", "> 3 MAD")) +
labs(x = "Number of UMIs", y = "Number of Cells", fill = "", color = "", tag = "C") +
theme_classic(base_size = 7) +
theme(plot.title = element_text(hjust = 0.5), legend.key.size = unit(7, "pt"), legend.position = "top", plot.tag = element_text(size = 9, face = "bold"))
umi.hist
ggsave(plot = umi.hist, filename = "umi-hist-plot-low-quality-cells.png", device = "png", units = "in", width = 2.16, height = 3)

Plot dots.
ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE), mapping = aes(x = nCount_RNA, y = 1, color = umi.out)) +
There were 19 warnings (use warnings() to see them)
geom_point(position = position_jitter(), size = 0.1) +
scale_x_continuous(trans = "log10")

So some upper and some lower range cells.
What does vln plot genes now look?
umi.plot <- ggplot(data = all.aggr@meta.data %>% filter(mito.out == FALSE) %>% filter(gene.out == FALSE)) +
geom_jitter(mapping = aes(y = nCount_RNA, x = umi.out, group = umi.out), stroke = 0, size = 0.1) +
geom_violin(mapping = aes(y = nCount_RNA, x = umi.out, color = umi.out), alpha = 0) +
scale_x_discrete(labels = c("<= 3MAD", "> 3MAD")) +
scale_y_continuous(trans = "log10", breaks=trans_breaks('log10', function(x) 10^x), labels=trans_format('log10', math_format(10^.x))) +
labs(x = "", y = "Number of UMIs", fill = "", color = "", tag = "C") +
theme_classic(base_size = 7) +
theme(plot.title = element_text(hjust = 0.5), legend.position = "none", plot.tag = element_text(size = 9, face = "bold"))
umi.plot
ggsave(plot = umi.plot, filename = "umi-vln-plot-low-quality-cells.png", device = "png", units = "in", width = 2.16, height = 4.5)

So a total of 768 for umi, 65 for gene, and 6681 for mito totaling 7457 cells. There is some overlap.
But there may be some overlap. Which cells are out for any one of these reasons?
all.aggr$all.out <- (all.aggr$mito.out == TRUE | all.aggr$gene.out == TRUE | all.aggr$umi.out == TRUE)
sum(all.aggr$all.out)
[1] 7457
So those are the cells to filter out.
Where are these cells along mito and genes?
ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA, color = all.out)) +
geom_point(size = 0.1) +
scale_x_continuous(trans = "log10") +
scale_y_continuous(trans = "log10")

ggplot(data = all.aggr@meta.data, mapping = aes(x = percent.mt, y = nFeature_RNA, color = all.out)) +
geom_point(size = 0.1) +
scale_x_continuous(trans = "log10") +
scale_y_continuous(trans = "log10") +
facet_wrap(~label.embryo)

How about along gene and umi?
ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, y = nFeature_RNA, color = all.out)) +
geom_point(size = 0.1) +
scale_x_continuous(trans = "log10") +
scale_y_continuous(trans = "log10") +
facet_wrap(~all.out)

ggplot(data = all.aggr@meta.data, mapping = aes(x = nCount_RNA, y = nFeature_RNA, color = all.out)) +
geom_point(size = 0.1) +
scale_x_continuous(trans = "log10") +
scale_y_continuous(trans = "log10")

facet_wrap(~label.embryo)
<ggproto object: Class FacetWrap, Facet, gg>
compute_layout: function
draw_back: function
draw_front: function
draw_labels: function
draw_panels: function
finish_data: function
init_scales: function
map_data: function
params: list
setup_data: function
setup_params: function
shrink: TRUE
train_scales: function
vars: function
super: <ggproto object: Class FacetWrap, Facet, gg>
Let’s remove those cells.
all.out <- all.aggr$all.out
save(all.out, file = "/Volumes/all_ssd/20220414-seurat/all-out-all-aggr.Robj")
scp /Volumes/all_ssd/20220414-seurat/all-out-all-aggr.Robj schea2@hpc3.rcic.uci.edu:/share/crsp/lab/alcalof/schea2/20220414-seurat
high.cells <- all.aggr@meta.data %>% filter(all.out == FALSE)
head(high.cells)
How many cells per embryo?
table(high.cells$label.embryo)
LB1 LB2 LB3 LB4 LB5 LB6 LB7 LB8 LB9 LB10 LB11 CC1 CC2 CC3 CC4 CC5 CC6 CC7 CC8 CC9 CC10 CC11 CC12 CC13 CC14 CC15 CC16
2493 1297 2602 7041 2338 1626 1450 4073 4010 3433 4823 1858 3537 4550 5202 7448 7759 4767 6573 2104 2197 669 1614 2025 3683 4919 8236
Median UMIs per cell per embryo?
high.cells %>% group_by(label.embryo) %>% summarise(median(nCount_RNA))
Median genes per cell per embryo?
high.cells %>% group_by(label.embryo) %>% summarise(median(nFeature_RNA))
Median UMIs per cell per stage per genotype?
high.cells %>% group_by(stage, genotype) %>% summarise(median(nCount_RNA))
`summarise()` has grouped output by 'stage'. You can override using the `.groups` argument.
Median genes per cell per stage per genotype?
high.cells %>% group_by(stage, genotype) %>% summarise(median(nFeature_RNA))
`summarise()` has grouped output by 'stage'. You can override using the `.groups` argument.
Median UMIs per cell per stage per genotype?
high.cells %>% group_by(stage) %>% summarise(median(nCount_RNA))
Median genes per cell per stage per genotype?
high.cells %>% group_by(stage) %>% summarise(median(nFeature_RNA))
Median UMIs per cell per stage per genotype?
high.cells %>% group_by(genotype) %>% summarise(median(nCount_RNA))
Median genes per cell per stage per genotype?
high.cells %>% group_by(genotype) %>% summarise(median(nFeature_RNA))
Median UMIs per cell?
median(high.cells$nCount_RNA)
[1] 15429
Median genes per cell?
median(high.cells$nFeature_RNA)
[1] 3676
LS0tCnRpdGxlOiAiV2hpY2ggY2VsbHMgYXJlIGxvdyBxdWFsaXR5IGNlbGxzPyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKRG93bmxvYWQgU2V1cmF0IG9iamVjdC4KYGBge2Jhc2h9CiNzY3Agc2NoZWEyQGhwYzMucmNpYy51Y2kuZWR1Oi9zaGFyZS9jcnNwL2xhYi9hbGNhbG9mL3NjaGVhMi8yMDIyMDQxNC1zZXVyYXQvYWxsLWFnZ3Itc2V1cmF0LlJvYmogL1ZvbHVtZXMvYWxsX3NzZC8yMDIyMDQxNC1zZXVyYXQKYGBgCgpMb2FkIGxpYnJhcmllcy4KYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShwcmFjbWEpCmxpYnJhcnkoc2NhbGVzKQpgYGAKCkxvYWQgU2V1cmF0IG9iamVjdC4KYGBge3J9CmxvYWQoIi9Wb2x1bWVzL2FsbF9zc2QvMjAyMjA0MTQtc2V1cmF0L2FsbC1hZ2dyLXNldXJhdC5Sb2JqIikKYGBgCgpQbG90IGhpc3RvZ3JhbSBvZiBudW1iZXIgb2YgdW1pJ3MuCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKGFsbC5hZ2dyJG5Db3VudF9STkEpLCBjb2xvciA9ICJibHVlIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IG1lZGlhbihhbGwuYWdnciRuQ291bnRfUk5BKSwgY29sb3IgPSAicmVkIikgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCmBgYAoKUGxvdCBoaXN0b2dyYW0gb2YgbnVtYmVyIG9mIGdlbmVzLgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IG5GZWF0dXJlX1JOQSkpICsKICBnZW9tX2hpc3RvZ3JhbSgpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWFuKGFsbC5hZ2dyJG5GZWF0dXJlX1JOQSksIGNvbG9yID0gImJsdWUiKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVkaWFuKGFsbC5hZ2dyJG5GZWF0dXJlX1JOQSksIGNvbG9yID0gInJlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKCkNhbGN1bGF0ZSAlIG1pdG9jaG9uZHJpYWwgZ2VuZXMuCmBgYHtyfQphbGwuYWdncltbInBlcmNlbnQubXQiXV0gPC0gUGVyY2VudGFnZUZlYXR1cmVTZXQoYWxsLmFnZ3IsIHBhdHRlcm4gPSAiXm10LSIpCmhlYWQoYWxsLmFnZ3JAbWV0YS5kYXRhKQpgYGAKClBsb3QgaGlzdG9ncmFtIG9mICUgbWl0b2Nob25kcmlhbCBnZW5lcy4KYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBwZXJjZW50Lm10KSkgKwogIGdlb21faGlzdG9ncmFtKCkgKwogICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihhbGwuYWdnciRwZXJjZW50Lm10KSwgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWRpYW4oYWxsLmFnZ3IkcGVyY2VudC5tdCksIGNvbG9yID0gInJlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKTGFyZ2VzdCBwb3J0aW9uIG9mIGRpc3RyaWJ1dGlvbiBub3JtYWwuIE9idmlvdXMgaHVtcCBvZiBjZWxscyB3aXRoIGxvdyAlIG1pdG9jaG9uZHJpYWwgZ2VuZXMuIE9kZCB0aGF0IHRoZXkgaGF2ZSBsb3cgJSBtaXRvY2hvbmRyaWFsIGdlbmVzLiBVc3VhbGx5IGxvdyBpcyBiZXR0ZXIsIGJ1dCBoZXJlLCBtb3N0IGNlbGxzIGhhdmUgYSAlIGJldHdlZW4gMSBhbmQgMTAuCgolIG1pdG9jaG9uZHJpYWwgZ2VuZXMgaXMgZGVwZW5kZW50IG9uIG51bWJlciBvZiBnZW5lcyBkZXRlY3RlZC4gRG8gdGhlc2UgY29ycmVwb25kIHRvIGNlbGxzIHdpdGggbG93IG51bWJlcnMgb2YgZ2VuZXM/CmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gcGVyY2VudC5tdCwgeSA9IG5GZWF0dXJlX1JOQSkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICAgICAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gbWVhbihhbGwuYWdnciRwZXJjZW50Lm10KSwgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSBtZWRpYW4oYWxsLmFnZ3IkcGVyY2VudC5tdCksIGNvbG9yID0gInJlZCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikKYGBgCgpDYWxjdWxhdGUgb3V0bGllcnMgdXNpbmcgbWVkaWFuIGFic29sdXRlIGRldmlhdGlvbi4KYGBge3J9CmFsbC5hZ2dyJGxvZy5taXRvIDwtIGxvZzEwKGFsbC5hZ2dyJHBlcmNlbnQubXQpCm1lZGlhbi5taXRvIDwtIG1lZGlhbihhbGwuYWdnciRsb2cubWl0bykKYWxsLmFnZ3IkZC5taXRvIDwtIGFicyhhbGwuYWdnciRsb2cubWl0byAtIG1lZGlhbi5taXRvKQptZC5taXRvIDwtIG1hZChhbGwuYWdnciRsb2cubWl0bykKYWxsLmFnZ3IkbWl0by5vdXQgPC0gYWxsLmFnZ3IkZC5taXRvID4gbWQubWl0byozCnN1bShhbGwuYWdnciRtaXRvLm91dCkKYGBgCgpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IHBlcmNlbnQubXQsIHkgPSBuRmVhdHVyZV9STkEsIGNvbG9yID0gbWl0by5vdXQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCgpgYGAKCldoYXQgZG9lcyBoaXN0b2dyYW0gb2YgJSBtaXRvIG5vdyBsb29rPwpgYGB7cn0KbWl0by5oaXN0IDwtIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBwZXJjZW50Lm10LCBmaWxsID0gbWl0by5vdXQsIGNvbG9yID0gbWl0by5vdXQpLCBhbHBoYSA9IDAuNSwgc2l6ZSA9IDAuMzMpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KHNjYWxlID0gMSkpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKGxhYmVscyA9IGMoIjw9MyBNQUQiLCAiPiAzIE1BRCIpKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiPD0zIE1BRCIsICI+IDMgTUFEIikpICsKICBsYWJzKHggPSAiJSBNaXRvY2hvbmRyaWFsIEdlbmVzIiwgeSA9ICJOdW1iZXIgb2YgQ2VsbHMiLCBmaWxsID0gIiIsIGNvbG9yID0gIiIsIHRhZyA9ICJBIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gNykgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDcsICJwdCIpLCBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgcGxvdC50YWcgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIpKQoKbWl0by5oaXN0CgpnZ3NhdmUocGxvdCA9IG1pdG8uaGlzdCwgZmlsZW5hbWUgPSAibWl0by1oaXN0LXBsb3QtbG93LXF1YWxpdHktY2VsbHMucG5nIiwgZGV2aWNlID0gInBuZyIsIHVuaXRzID0gImluIiwgd2lkdGggPSAyLjE2LCBoZWlnaHQgPSAzKQoKYGBgCgpHZW5lcz8KYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBuRmVhdHVyZV9STkEsIGNvbG9yID0gbWl0by5vdXQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikKYGBgCgpVTUlzPwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IG5Db3VudF9STkEsIGNvbG9yID0gbWl0by5vdXQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikKYGBgCgpXaGF0IGRvZXMgdmxuIHBsb3QgbWl0byBub3cgbG9vaz8KYGBge3J9Cm1pdG8ucGxvdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9qaXR0ZXIoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh5ID0gcGVyY2VudC5tdCwgeCA9IG1pdG8ub3V0LCBncm91cCA9IG1pdG8ub3V0KSwgc3Ryb2tlID0gMCwgc2l6ZSA9IDAuMjUpICsKICBnZW9tX3Zpb2xpbihkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHkgPSBwZXJjZW50Lm10LCB4ID0gbWl0by5vdXQsIGNvbG9yID0gbWl0by5vdXQpLCBhbHBoYSA9IDApICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIjw9IDNNQUQiLCAiPiAzTUFEIikpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KHNjYWxlID0gMSkpICsKICBsYWJzKHggPSAiIiwgeSA9ICIlIE1pdG9jaG9uZHJpYWwgR2VuZXMiLCBmaWxsID0gIiIsIGNvbG9yID0gIiIsIHRhZyA9ICJBIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gNykgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIHBsb3QudGFnID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkKCm1pdG8ucGxvdAoKZ2dzYXZlKHBsb3QgPSBtaXRvLnBsb3QsIGZpbGVuYW1lID0gIm1pdG8tdmxuLXBsb3QtbG93LXF1YWxpdHktY2VsbHMucG5nIiwgZGV2aWNlID0gInBuZyIsIHVuaXRzID0gImluIiwgd2lkdGggPSAyLjE2LCBoZWlnaHQgPSA0LjUpCmBgYAoKQ2FuIHdlIGZpbmQgb3V0bGllcnMgYW1vbmcgZ2VuZXMgYWZ0ZXIgYWxyZWFkeSBmaWx0ZXJpbmcgb3V0IG91dGxpZXJzIGZyb20gbWl0bz8KYGBge3J9CmFsbC5hZ2dyJGxvZy5nZW5lIDwtIGxvZzEwKGFsbC5hZ2dyJG5GZWF0dXJlX1JOQSkKbWVkaWFuLmdlbmUgPC0gbWVkaWFuKGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSAlPiUgcHVsbChsb2cuZ2VuZSkpCmFsbC5hZ2dyJGQuZ2VuZSA8LSBhYnMoYWxsLmFnZ3IkbG9nLmdlbmUgLSBtZWRpYW4uZ2VuZSkKbWQuZ2VuZSA8LSBtYWQoYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIobWl0by5vdXQgPT0gRkFMU0UpICU+JSBwdWxsKGxvZy5nZW5lKSkKYWxsLmFnZ3IkZ2VuZS5vdXQgPC0gYWxsLmFnZ3IkZC5nZW5lID4gbWQuZ2VuZSozCnN1bShhbGwuYWdnciRnZW5lLm91dCkKYGBgCgpXaGVyZSBkbyB0aGVzZSBjZWxscyBsaWUgYWxvbmcgaGlzdG9ncmFtIG9mIG51bWJlciBvZiBnZW5lcz8KYGBge3J9CmdlbmUuaGlzdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9oaXN0b2dyYW0oZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSwgbWFwcGluZyA9IGFlcyh4ID0gbkZlYXR1cmVfUk5BLCBmaWxsID0gZ2VuZS5vdXQsIGNvbG9yID0gZ2VuZS5vdXQpLCBhbHBoYSA9IDAuNSwgc2l6ZSA9IDAuMzMpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBicmVha3M9dHJhbnNfYnJlYWtzKCdsb2cxMCcsIGZ1bmN0aW9uKHgpIDEwXngpLCBsYWJlbHM9dHJhbnNfZm9ybWF0KCdsb2cxMCcsIG1hdGhfZm9ybWF0KDEwXi54KSkpICsKICBzY2FsZV9maWxsX2Rpc2NyZXRlKGxhYmVscyA9IGMoIjw9MyBNQUQiLCAiPiAzIE1BRCIpKSArCiAgc2NhbGVfY29sb3JfZGlzY3JldGUobGFiZWxzID0gYygiPD0zIE1BRCIsICI+IDMgTUFEIikpICsKICBsYWJzKHggPSAiTnVtYmVyIG9mIEdlbmVzIiwgeSA9ICJOdW1iZXIgb2YgQ2VsbHMiLCBmaWxsID0gIiIsIGNvbG9yID0gIiIsIHRhZyA9ICJCIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gNykgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQua2V5LnNpemUgPSB1bml0KDcsICJwdCIpLCBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgcGxvdC50YWcgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIpKQoKZ2VuZS5oaXN0IAoKZ2dzYXZlKHBsb3QgPSBnZW5lLmhpc3QsIGZpbGVuYW1lID0gImdlbmUtaGlzdC1wbG90LWxvdy1xdWFsaXR5LWNlbGxzLnBuZyIsIGRldmljZSA9ICJwbmciLCB1bml0cyA9ICJpbiIsIHdpZHRoID0gMi4xNiwgaGVpZ2h0ID0gMykKCgpgYGAKCkFsb25nIG51bWJlciBvZiB1bWlzPwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEgJT4lIGZpbHRlcihtaXRvLm91dCA9PSBGQUxTRSksIG1hcHBpbmcgPSBhZXMoeCA9IG5Db3VudF9STkEsIGNvbG9yID0gZ2VuZS5vdXQpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikKYGBgCgpXaGF0IGRvZXMgdmxuIHBsb3QgZ2VuZXMgbm93IGxvb2s/CmBgYHtyfQpnZW5lLnBsb3QgPC0gZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEgJT4lIGZpbHRlcihtaXRvLm91dCA9PSBGQUxTRSkpICsKICBnZW9tX2ppdHRlcihtYXBwaW5nID0gYWVzKHkgPSBuRmVhdHVyZV9STkEsIHggPSBnZW5lLm91dCwgZ3JvdXAgPSBnZW5lLm91dCksIHN0cm9rZSA9IDAsIHNpemUgPSAwLjI1KSArCiAgZ2VvbV92aW9saW4obWFwcGluZyA9IGFlcyh5ID0gbkZlYXR1cmVfUk5BLCB4ID0gZ2VuZS5vdXQsIGNvbG9yID0gZ2VuZS5vdXQpLCBhbHBoYSA9IDApICsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGMoIjw9IDNNQUQiLCAiPiAzTUFEIikpICsKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBicmVha3M9dHJhbnNfYnJlYWtzKCdsb2cxMCcsIGZ1bmN0aW9uKHgpIDEwXngpLCBsYWJlbHM9dHJhbnNfZm9ybWF0KCdsb2cxMCcsIG1hdGhfZm9ybWF0KDEwXi54KSkpICsKICBsYWJzKHggPSAiIiwgeSA9ICJOdW1iZXIgb2YgR2VuZXMiLCBmaWxsID0gIiIsIGNvbG9yID0gIiIsIHRhZyA9ICJCIikgKwogIHRoZW1lX2NsYXNzaWMoYmFzZV9zaXplID0gNykgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsICwgcGxvdC50YWcgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDksIGZhY2UgPSAiYm9sZCIpKQoKZ2VuZS5wbG90CgpnZ3NhdmUocGxvdCA9IGdlbmUucGxvdCwgZmlsZW5hbWUgPSAiZ2VuZS12bG4tcGxvdC1sb3ctcXVhbGl0eS1jZWxscy5wbmciLCBkZXZpY2UgPSAicG5nIiwgdW5pdHMgPSAiaW4iLCB3aWR0aCA9IDIuMTYsIGhlaWdodCA9IDQuNSkKYGBgCgpDYW4gd2UgZmluZCBvdXRsaWVycyBhbW9uZyB1bWlzIGFmdGVyIGFscmVhZHkgZmlsdGVyaW5nIG91dCBtaXRvIGFuZCBnZW5lcz8KYGBge3J9CmFsbC5hZ2dyJGxvZy51bWkgPC0gbG9nMTAoYWxsLmFnZ3IkbkNvdW50X1JOQSkKbWVkaWFuLnVtaSA8LSBtZWRpYW4oYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIobWl0by5vdXQgPT0gRkFMU0UpICU+JSBmaWx0ZXIoZ2VuZS5vdXQgPT0gRkFMU0UpICU+JSBwdWxsKGxvZy51bWkpKQphbGwuYWdnciRkLnVtaSA8LSBhYnMoYWxsLmFnZ3IkbG9nLnVtaSAtIG1lZGlhbi51bWkpCm1kLnVtaSA8LSBtYWQoYWxsLmFnZ3JAbWV0YS5kYXRhICU+JSBmaWx0ZXIobWl0by5vdXQgPT0gRkFMU0UpICU+JSBmaWx0ZXIoZ2VuZS5vdXQgPT0gRkFMU0UpICU+JSBwdWxsKGxvZy51bWkpKQphbGwuYWdnciR1bWkub3V0IDwtIGFsbC5hZ2dyJGQudW1pID4gbWQudW1pKjMKc3VtKGFsbC5hZ2dyJHVtaS5vdXQpCmBgYAoKV2hlcmUgZG8gdGhlc2UgbGllIGFsb25nIHVtaXM/CmBgYHtyfQp1bWkuaGlzdCA8LSBnZ3Bsb3QoKSArCiAgZ2VvbV9oaXN0b2dyYW0oZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSAlPiUgZmlsdGVyKGdlbmUub3V0ID09IEZBTFNFKSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgY29sb3IgPSB1bWkub3V0LCBmaWxsID0gdW1pLm91dCksIGFscGhhID0gMC41LCBzaXplID0gMC4zMykgKwogIHNjYWxlX3hfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIGJyZWFrcz10cmFuc19icmVha3MoJ2xvZzEwJywgZnVuY3Rpb24oeCkgMTBeeCksIGxhYmVscz10cmFuc19mb3JtYXQoJ2xvZzEwJywgbWF0aF9mb3JtYXQoMTBeLngpKSkgKwogIHNjYWxlX2ZpbGxfZGlzY3JldGUobGFiZWxzID0gYygiPD0zIE1BRCIsICI+IDMgTUFEIikpICsKICBzY2FsZV9jb2xvcl9kaXNjcmV0ZShsYWJlbHMgPSBjKCI8PTMgTUFEIiwgIj4gMyBNQUQiKSkgKwogIGxhYnMoeCA9ICJOdW1iZXIgb2YgVU1JcyIsIHkgPSAiTnVtYmVyIG9mIENlbGxzIiwgZmlsbCA9ICIiLCBjb2xvciA9ICIiLCB0YWcgPSAiQyIpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDcpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLmtleS5zaXplID0gdW5pdCg3LCAicHQiKSwgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsIHBsb3QudGFnID0gZWxlbWVudF90ZXh0KHNpemUgPSA5LCBmYWNlID0gImJvbGQiKSkKCnVtaS5oaXN0CgpnZ3NhdmUocGxvdCA9IHVtaS5oaXN0LCBmaWxlbmFtZSA9ICJ1bWktaGlzdC1wbG90LWxvdy1xdWFsaXR5LWNlbGxzLnBuZyIsIGRldmljZSA9ICJwbmciLCB1bml0cyA9ICJpbiIsIHdpZHRoID0gMi4xNiwgaGVpZ2h0ID0gMykKYGBgCgpQbG90IGRvdHMuCmBgYHtyfQpnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSAlPiUgZmlsdGVyKGdlbmUub3V0ID09IEZBTFNFKSwgbWFwcGluZyA9IGFlcyh4ID0gbkNvdW50X1JOQSwgeSA9IDEsIGNvbG9yID0gdW1pLm91dCkpICsKICBnZW9tX3BvaW50KHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKCksIHNpemUgPSAwLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKQpgYGAKU28gc29tZSB1cHBlciBhbmQgc29tZSBsb3dlciByYW5nZSBjZWxscy4gCgpXaGF0IGRvZXMgdmxuIHBsb3QgZ2VuZXMgbm93IGxvb2s/CmBgYHtyfQp1bWkucGxvdCA8LSBnZ3Bsb3QoZGF0YSA9IGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKG1pdG8ub3V0ID09IEZBTFNFKSAlPiUgZmlsdGVyKGdlbmUub3V0ID09IEZBTFNFKSkgKwogIGdlb21faml0dGVyKG1hcHBpbmcgPSBhZXMoeSA9IG5Db3VudF9STkEsIHggPSB1bWkub3V0LCBncm91cCA9IHVtaS5vdXQpLCBzdHJva2UgPSAwLCBzaXplID0gMC4xKSArCiAgZ2VvbV92aW9saW4obWFwcGluZyA9IGFlcyh5ID0gbkNvdW50X1JOQSwgeCA9IHVtaS5vdXQsIGNvbG9yID0gdW1pLm91dCksIGFscGhhID0gMCkgKwogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gYygiPD0gM01BRCIsICI+IDNNQUQiKSkgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIsIGJyZWFrcz10cmFuc19icmVha3MoJ2xvZzEwJywgZnVuY3Rpb24oeCkgMTBeeCksIGxhYmVscz10cmFuc19mb3JtYXQoJ2xvZzEwJywgbWF0aF9mb3JtYXQoMTBeLngpKSkgKwogIGxhYnMoeCA9ICIiLCB5ID0gIk51bWJlciBvZiBVTUlzIiwgZmlsbCA9ICIiLCBjb2xvciA9ICIiLCB0YWcgPSAiQyIpICsKICB0aGVtZV9jbGFzc2ljKGJhc2Vfc2l6ZSA9IDcpICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCBwbG90LnRhZyA9IGVsZW1lbnRfdGV4dChzaXplID0gOSwgZmFjZSA9ICJib2xkIikpCgp1bWkucGxvdAoKZ2dzYXZlKHBsb3QgPSB1bWkucGxvdCwgZmlsZW5hbWUgPSAidW1pLXZsbi1wbG90LWxvdy1xdWFsaXR5LWNlbGxzLnBuZyIsIGRldmljZSA9ICJwbmciLCB1bml0cyA9ICJpbiIsIHdpZHRoID0gMi4xNiwgaGVpZ2h0ID0gNC41KQpgYGAKClNvIGEgdG90YWwgb2YgNzY4IGZvciB1bWksIDY1IGZvciBnZW5lLCBhbmQgNjY4MSBmb3IgbWl0byB0b3RhbGluZyA3NDU3IGNlbGxzLiBUaGVyZSBpcyBzb21lIG92ZXJsYXAuCgpCdXQgdGhlcmUgbWF5IGJlIHNvbWUgb3ZlcmxhcC4gV2hpY2ggY2VsbHMgYXJlIG91dCBmb3IgYW55IG9uZSBvZiB0aGVzZSByZWFzb25zPwpgYGB7cn0KYWxsLmFnZ3IkYWxsLm91dCA8LSAoYWxsLmFnZ3IkbWl0by5vdXQgPT0gVFJVRSB8IGFsbC5hZ2dyJGdlbmUub3V0ID09IFRSVUUgfCBhbGwuYWdnciR1bWkub3V0ID09IFRSVUUpCnN1bShhbGwuYWdnciRhbGwub3V0KQpgYGAKU28gdGhvc2UgYXJlIHRoZSBjZWxscyB0byBmaWx0ZXIgb3V0LiAKCldoZXJlIGFyZSB0aGVzZSBjZWxscyBhbG9uZyBtaXRvIGFuZCBnZW5lcz8KYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBwZXJjZW50Lm10LCB5ID0gbkZlYXR1cmVfUk5BLCBjb2xvciA9IGFsbC5vdXQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBwZXJjZW50Lm10LCB5ID0gbkZlYXR1cmVfUk5BLCBjb2xvciA9IGFsbC5vdXQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikgKyAKICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKSArIAogIGZhY2V0X3dyYXAofmxhYmVsLmVtYnJ5bykKYGBgCgpIb3cgYWJvdXQgYWxvbmcgZ2VuZSBhbmQgdW1pPwpgYGB7cn0KZ2dwbG90KGRhdGEgPSBhbGwuYWdnckBtZXRhLmRhdGEsIG1hcHBpbmcgPSBhZXMoeCA9IG5Db3VudF9STkEsIHkgPSBuRmVhdHVyZV9STkEsIGNvbG9yID0gYWxsLm91dCkpICsKICBnZW9tX3BvaW50KHNpemUgPSAwLjEpICsKICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikgKwogIGZhY2V0X3dyYXAofmFsbC5vdXQpCmBgYAoKYGBge3J9CmdncGxvdChkYXRhID0gYWxsLmFnZ3JAbWV0YS5kYXRhLCBtYXBwaW5nID0gYWVzKHggPSBuQ291bnRfUk5BLCB5ID0gbkZlYXR1cmVfUk5BLCBjb2xvciA9IGFsbC5vdXQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gMC4xKSArCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIikgKwogIHNjYWxlX3lfY29udGludW91cyh0cmFucyA9ICJsb2cxMCIpCiAgZmFjZXRfd3JhcCh+bGFiZWwuZW1icnlvKQpgYGAKCkxldCdzIHJlbW92ZSB0aG9zZSBjZWxscy4KYGBge3J9CmFsbC5vdXQgPC0gYWxsLmFnZ3IkYWxsLm91dApzYXZlKGFsbC5vdXQsIGZpbGUgPSAiL1ZvbHVtZXMvYWxsX3NzZC8yMDIyMDQxNC1zZXVyYXQvYWxsLW91dC1hbGwtYWdnci5Sb2JqIikKYGBgCgpgYGB7YmFzaH0Kc2NwIC9Wb2x1bWVzL2FsbF9zc2QvMjAyMjA0MTQtc2V1cmF0L2FsbC1vdXQtYWxsLWFnZ3IuUm9iaiBzY2hlYTJAaHBjMy5yY2ljLnVjaS5lZHU6L3NoYXJlL2Nyc3AvbGFiL2FsY2Fsb2Yvc2NoZWEyLzIwMjIwNDE0LXNldXJhdApgYGAKCmBgYHtyfQpoaWdoLmNlbGxzIDwtIGFsbC5hZ2dyQG1ldGEuZGF0YSAlPiUgZmlsdGVyKGFsbC5vdXQgPT0gRkFMU0UpCmhlYWQoaGlnaC5jZWxscykKYGBgCgpIb3cgbWFueSBjZWxscyBwZXIgZW1icnlvPwpgYGB7cn0KdGFibGUoaGlnaC5jZWxscyRsYWJlbC5lbWJyeW8pCmBgYAoKTWVkaWFuIFVNSXMgcGVyIGNlbGwgcGVyIGVtYnJ5bz8KYGBge3J9CmhpZ2guY2VsbHMgJT4lIGdyb3VwX2J5KGxhYmVsLmVtYnJ5bykgJT4lIHN1bW1hcmlzZShtZWRpYW4obkNvdW50X1JOQSkpCmBgYAoKTWVkaWFuIGdlbmVzIHBlciBjZWxsIHBlciBlbWJyeW8/CmBgYHtyfQpoaWdoLmNlbGxzICU+JSBncm91cF9ieShsYWJlbC5lbWJyeW8pICU+JSBzdW1tYXJpc2UobWVkaWFuKG5GZWF0dXJlX1JOQSkpCmBgYAoKTWVkaWFuIFVNSXMgcGVyIGNlbGwgcGVyIHN0YWdlIHBlciBnZW5vdHlwZT8KYGBge3J9CmhpZ2guY2VsbHMgJT4lIGdyb3VwX2J5KHN0YWdlLCBnZW5vdHlwZSkgJT4lIHN1bW1hcmlzZShtZWRpYW4obkNvdW50X1JOQSkpCmBgYAoKTWVkaWFuIGdlbmVzIHBlciBjZWxsIHBlciBzdGFnZSBwZXIgZ2Vub3R5cGU/CmBgYHtyfQpoaWdoLmNlbGxzICU+JSBncm91cF9ieShzdGFnZSwgZ2Vub3R5cGUpICU+JSBzdW1tYXJpc2UobWVkaWFuKG5GZWF0dXJlX1JOQSkpCmBgYAoKTWVkaWFuIFVNSXMgcGVyIGNlbGwgcGVyIHN0YWdlIHBlciBnZW5vdHlwZT8KYGBge3J9CmhpZ2guY2VsbHMgJT4lIGdyb3VwX2J5KHN0YWdlKSAlPiUgc3VtbWFyaXNlKG1lZGlhbihuQ291bnRfUk5BKSkKYGBgCgpNZWRpYW4gZ2VuZXMgcGVyIGNlbGwgcGVyIHN0YWdlIHBlciBnZW5vdHlwZT8KYGBge3J9CmhpZ2guY2VsbHMgJT4lIGdyb3VwX2J5KHN0YWdlKSAlPiUgc3VtbWFyaXNlKG1lZGlhbihuRmVhdHVyZV9STkEpKQpgYGAKCk1lZGlhbiBVTUlzIHBlciBjZWxsIHBlciBzdGFnZSBwZXIgZ2Vub3R5cGU/CmBgYHtyfQpoaWdoLmNlbGxzICU+JSBncm91cF9ieShnZW5vdHlwZSkgJT4lIHN1bW1hcmlzZShtZWRpYW4obkNvdW50X1JOQSkpCmBgYAoKTWVkaWFuIGdlbmVzIHBlciBjZWxsIHBlciBzdGFnZSBwZXIgZ2Vub3R5cGU/CmBgYHtyfQpoaWdoLmNlbGxzICU+JSBncm91cF9ieShnZW5vdHlwZSkgJT4lIHN1bW1hcmlzZShtZWRpYW4obkZlYXR1cmVfUk5BKSkKYGBgCgpNZWRpYW4gVU1JcyBwZXIgY2VsbD8KYGBge3J9Cm1lZGlhbihoaWdoLmNlbGxzJG5Db3VudF9STkEpCmBgYAoKTWVkaWFuIGdlbmVzIHBlciBjZWxsPwpgYGB7cn0KbWVkaWFuKGhpZ2guY2VsbHMkbkZlYXR1cmVfUk5BKQpgYGAKCgoK